Micron Document
<!DOCTYPE html>
<html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-0 vector-toc-not-available vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-0 skin-theme-clientpref-day vector-sticky-header-enabled" lang="de" dir="ltr"><head>
<meta charset="UTF-8">
<title>Template (C++)</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="./_res_/favicon.png">
<link rel="canonical" href="https://de.wikipedia.org/wiki/Template_(C%2B%2B)"> <link href="./_mw_/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.wikimediamessages.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link href="./_mw_/ext.gadget.citeRef.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.defaultPlainlinks.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonHide.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonLayout.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonStyle.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiDarkmode.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiResponsive.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.specialSearch.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="./_mw_/site.styles.css">
<link rel="stylesheet" type="text/css" href="./_mw_/noscript.css">
<link rel="stylesheet" type="text/css" href="./_res_/footer.css">
<link rel="stylesheet" type="text/css" href="./_res_/vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Template_C rootpage-Template_C skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-main">Template (C++)</span></h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="contentSub">
<div id="mw-content-subtitle"></div>
</div>
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="de" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="de" dir="ltr"><p><b>Templates</b> (englisch für <b>Schablonen</b> oder <b>Vorlagen</b>) sind ein Mittel zur Typ<a href="Parameter_(Informatik)" title="Parameter (Informatik)">parametrierung</a> in <a href="C%2B%2B" title="C++">C++</a>. Templates ermöglichen <a href="Generische_Programmierung" title="Generische Programmierung">generische Programmierung</a> und <a href="Typsicherheit" title="Typsicherheit">typsichere</a> Container.
</p><p>In der <a href="C%2B%2B-Standardbibliothek" title="C++-Standardbibliothek">C++-Standardbibliothek</a> werden Templates zur Bereitstellung typsicherer Container, wie z.&nbsp;B. Listen, und zur Implementierung von generischen Algorithmen, wie z.&nbsp;B. <a href="Sortierverfahren" title="Sortierverfahren">Sortierverfahren</a>, verwendet. Die Templates in C++ sind wesentlich von den parametrierbaren Modulen in <a href="CLU_(Programmiersprache)" title="CLU (Programmiersprache)">CLU</a> und den Generics in <a href="Ada_(Programmiersprache)" title="Ada (Programmiersprache)">Ada</a> inspiriert.<sup id="cite_ref-Stroustrup_1-0" class="reference"><a href="#cite_note-Stroustrup-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>
</p><p>In anderen Programmiersprachen (z.&nbsp;B. <a href="Java_(Programmiersprache)" title="Java (Programmiersprache)">Java</a><sup id="cite_ref-2" class="reference"><a href="#cite_note-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> oder <a href="C_Sharp" class="mw-redirect" title="C Sharp">C#</a><sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>) gibt es das Konzept des <a href="Generischer_Typ" title="Generischer Typ">generischen Typs</a>, das mit Templates verwandt ist. Generische Typen stellen jedoch keine <a href="Codegenerator" title="Codegenerator">Codegeneratoren</a> dar, sondern ermöglichen lediglich typsichere Container und Algorithmen.
</p>

<div class="mw-heading mw-heading2"><h2 id="Arten_von_Templates">Arten von Templates</h2></div>
<p>Es gibt in C++ drei Arten von Templates: <i>Funktions-Templates</i>, <i>Klassen-Templates</i> und <i>Variablen-Templates</i>:
</p>
<div class="mw-heading mw-heading3"><h3 id="Funktions-Templates">Funktions-Templates</h3></div>
<p>Ein <i>Funktions-Template</i> (auch fälschlich <i>Template-Funktion</i> genannt) verhält sich wie eine Funktion, die Argumente verschiedener Typen akzeptiert oder unterschiedliche Rückgabetypen liefert. Die C++-Standardbibliothek enthält beispielsweise das Funktions-Template <code>std::max(x, y)</code>, welches das größere der beiden Argumente zurückgibt. Es könnte etwa folgendermaßen definiert sein:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">max</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>

<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">y</span><span class="p">)</span>
<span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>

<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Dieses Template kann genauso aufgerufen werden wie eine Funktion:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">max</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">7</span><span class="p">);</span><span class="w"> </span><span class="c1">// gibt 7 aus</span>
</pre></div>
<p>Anhand der Argumente entscheidet der Compiler, dass es sich um einen Aufruf an <code>max(int, int)</code> handelt, und erzeugt eine Variante der Funktion, bei der der generische Typ <span style="font-family:monospace;">T</span> zu <span style="font-family:monospace;">int</span> festgelegt wird.
</p><p>Der Template-Parameter könnte auch explizit angegeben werden:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">max</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">7</span><span class="p">);</span><span class="w"> </span><span class="c1">// gibt ebenfalls "7" aus</span>
</pre></div>
<p>Das Funktions-Template <code>max()</code> lässt sich für jeden Typ instanziieren, für den der Vergleich <code>x &lt; y</code> eine wohldefinierte Operation darstellt. Bei selbstdefinierten Typen macht man von Operator-<a href="%C3%9Cberladen" title="Überladen">Überladung</a> Gebrauch, um die Bedeutung von <code>&lt;</code> für den Typ festzulegen und dadurch die Verwendung von <code>max()</code> für den betreffenden Typ zu ermöglichen.
</p><p>Im Zusammenspiel mit der C++-Standardbibliothek erschließt sich eine enorme Funktionalität für selbstdefinierte Typen durch Definition einiger Operatoren. Allein durch die Definition eines Vergleichsoperators <code>&lt;</code> (<a href="Strenge_schwache_Ordnung" title="Strenge schwache Ordnung">strenge schwache Ordnung</a>) werden die Standardalgorithmen <code>std::sort()</code>, <code>std::stable_sort()</code>, und <code>std::binary_search()</code> für den selbstdefinierten Typ anwendbar.
</p>
<div class="mw-heading mw-heading3"><h3 id="Klassen-Templates">Klassen-Templates</h3></div>
<p>Ein <i>Klassen-Template</i> (deutsch: <i>Klassenvorlage</i>, auch fälschlich <i>Template-Klasse</i> genannt), wendet das gleiche Prinzip auf Klassen an. Klassen-Templates werden oft zur Erstellung von generischen Containern verwendet. Beispielsweise enthält die C++-Standardbibliothek einen Container, der eine verkettete Liste implementiert. Um eine verkettete Liste von <span style="font-family:monospace;">int</span> zu erstellen, schreibt man <code>std::list&lt;int&gt;</code>. Eine verkettete Liste von Objekten des Datentypes <code>std::string</code> wird zu <code>std::list&lt;std::string&gt;</code>. Mit <span style="font-family:monospace;">list</span> ist ein Satz von Standardfunktionen definiert, die immer verfügbar sind, unabhängig davon, was man als Argumenttyp in den spitzen Klammern angibt. Die Werte in spitzen Klammern werden Parameter genannt. Wenn ein Klassen-Template mit seinen Parametern dem Compiler übergeben wird, so kann dieser das Template ausprägen. Er erzeugt hierbei zu jedem Parametertyp eine eigene Template-Klasse. Diese ist eine <i>gewöhnliche</i> Klasse, wie jede andere auch. Die Begriffe Klassen-Template und Template-Klasse sind hier voneinander zu unterscheiden. Wie <i>Objekt</i> und <i>Klasse</i> ist die Template-Klasse eine Ausprägung eines Klassen-Templates.
</p><p>Templates sind sowohl für mit <span style="font-family:monospace;">class</span> als auch für mit <span style="font-family:monospace;">struct</span> und <span style="font-family:monospace;">union</span> definierte Klassen anwendbar. Namespaces (deutsch: Namensräume) lassen sich dagegen nicht als Template anlegen. Eine Möglichkeit, Typ-Definitionen per „typedef“ als Templates anzulegen, kam mit C++11 hinzu.
</p>
<div class="mw-heading mw-heading4"><h4 id="Vererbung">Vererbung</h4></div>
<p>Klassen-Templates können wie normale Klassen in Vererbungshierarchien sowohl als Basis- als auch als abgeleitete Klasse auftreten.
</p><p>Wird ein Klassen-Template mit verschiedenen Klassenparametern ausgeprägt, so stehen diese grundsätzlich in keiner Vererbungsrelation – auch nicht, wenn die Template-Parameter in einer Vererbungsbeziehung stehen.
</p>
<dl><dt>Beispiel</dt>
<dd></dd></dl>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{...};</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="o">:</span><span class="w"> </span><span class="n">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">};</span>

<span class="n">Base</span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Derived</span><span class="p">;</span><span class="w"> </span><span class="c1">// OK. Automatische Typumwandlung, da Basisklasse.</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Base</span><span class="o">&gt;*</span><span class="w"> </span><span class="n">vb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Derived</span><span class="o">&gt;</span><span class="p">;</span><span class="w"> </span><span class="c1">// FEHLER!</span>
</pre></div>
<p>Es gibt vor allem zwei Gründe, wieso derartige Umwandlungen nicht erlaubt sind:
</p><p>Zum einen sind es technische Gründe: Ein <code>std::vector&lt;T&gt;</code> speichert seine Elemente in einem Array an unmittelbar aufeinander folgenden Adressen. Wenn nun ein Objekt vom Typ <code>Derived</code> eine andere Größe hat als ein Objekt vom Typ <code>Base</code>, dann stimmt das Speicherlayout von einem <code>std::vector&lt;Base&gt;</code> nicht mehr mit dem eines <code>std::vector&lt;Derived&gt;</code> überein und der Zugriff auf die Elemente würde fehlschlagen.
</p><p>Zum anderen hat es aber auch programmlogische Gründe: Ein Container, der Elemente einer Basisklasse enthält, verweist auf Elemente, deren Datentyp <code>Base</code> ist oder von <code>Base</code> abgeleitet sind. Er ist somit einerseits mächtiger als ein Container, der <i>nur</i> Elemente vom Typ <code>Derived</code> aufnehmen kann, andererseits weniger mächtig, da er <i>nur</i> garantiert Elemente vom Type <code>Base</code> zurückzugeben.
Für <code>std::vector&lt;T&gt;</code> illustriert das am einfachsten der <code>[]</code> operator.
</p>
<dl><dt>Beispiel</dt>
<dd></dd></dl>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{...};</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="o">:</span><span class="w"> </span><span class="n">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">};</span>

<span class="n">Base</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Base</span><span class="p">;</span>
<span class="n">Derived</span><span class="o">*</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Derived</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Base</span><span class="o">&gt;</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">vb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Base</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Derived</span><span class="o">&gt;*</span><span class="w"> </span><span class="n">vd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Derived</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>
<p>Einerseits kann man <code>vb[0] = b</code> nicht aber <code>vd[0] = b</code> schreiben.
Andererseits kann man <code>d = vd[0]</code> nicht aber <code>d = vb[0]</code> schreiben.
</p><p>Falls eine Umwandlung von verschiedenen Ausprägungen desselben Klassen-Templates – wie etwa bei <code>std::shared_ptr</code> – sinnvoll ist, muss dafür explizit ein Typkonvertierungsoperator definiert werden.
</p>
<div class="mw-heading mw-heading3"><h3 id="Variablen-Templates">Variablen-Templates</h3></div>
<p>Seit C++14 ist es auch möglich, Variablen-Templates zu definieren. Das ermöglicht es, Variablen, die logisch zusammen gehören bzw. bis auf den Typ „dasselbe“ sind, entsprechend kenntlich zu machen:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="c1">// variable template</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Pi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">T</span><span class="p">(</span><span class="mf">3.1415926535897932385L</span><span class="p">);</span>

<span class="c1">// function template</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">kreisflaeche</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">Pi</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">r</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Die Funktion <code>kreisflaeche()</code> kann nun für verschiedene arithmetische Datentypen instanziiert werden und greift dabei stets auf eine vom Parametertyp her passende Konstante <code>Pi</code> zu.
</p>
<div class="mw-heading mw-heading2"><h2 id="Spezialisierung">Spezialisierung</h2></div>
<p>Templates lassen sich <i>spezialisieren</i>, d.&nbsp;h., man kann Klassen- und Funktions-Templates (für bestimmte Datentypen als Template-Argumente) gesondert implementieren. Dies erlaubt eine effizientere Implementierung für bestimmte ausgewählte Datentypen, ohne die Schnittstelle des Templates zu verändern. Davon machen auch viele Implementierungen der C++-Standardbibliothek (beispielsweise die der <a href="GNU_Compiler_Collection" title="GNU Compiler Collection">GCC</a>) Gebrauch.
</p>
<div class="mw-heading mw-heading3"><h3 id="Spezialisierung_bei_Klassen-Templates">Spezialisierung bei Klassen-Templates</h3></div>
<p>Die Containerklasse <code>std::vector</code> der C++-Standardbibliothek kann für den Elementtyp <span style="font-family:monospace;">bool</span> als <i>Bitmap</i> implementiert werden, um Speicherplatz einzusparen. Auch entnimmt das Klassen-Template <code>std::basic_string</code> die Informationen zum Umgang mit den einzelnen Zeichen der Struktur <span style="font-family:monospace;">char_traits</span>, die für den Datentyp <span style="font-family:monospace;">char</span> und beispielsweise auch <span style="font-family:monospace;">wchar_t</span> spezialisiert ist.
</p><p>Die Deklaration von Spezialisierungen ähnelt der von normalen Templates. Allerdings sind die dem Schlüsselwort <span style="font-family:monospace;">template</span> folgenden spitzen Klammern leer, und dem Funktions- bzw. Klassennamen folgen die Template-Parameter.
</p>
<dl><dt>Beispiel</dt>
<dd></dd></dl>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="o">&lt;&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Implementierung von vector als Bitmap</span>
<span class="p">};</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Partielle_Spezialisierung">Partielle Spezialisierung</h3></div>
<p>Weiterhin gibt es auch die sogenannte <b>partielle Spezialisierung</b>, die die Behandlung von Spezialfällen innerhalb eines Templates ermöglicht.
</p>
<dl><dt>Beispiel</dt>
<dd></dd></dl>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="o">&lt;</span><span class="kt">int</span><span class="w"> </span><span class="n">zeilen</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">spalten</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Matrix</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Implementierung einer Matrix-Klasse</span>
<span class="p">};</span>

<span class="k">template</span><span class="o">&lt;</span><span class="kt">int</span><span class="w"> </span><span class="n">zeilen</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Matrix</span><span class="o">&lt;</span><span class="n">zeilen</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Implementierung einer einspaltigen Matrix-Klasse</span>
<span class="p">};</span>
</pre></div>
<p>Die Instanziierung läuft bei der spezialisierten Klasse im Grunde gleich ab, es wird nur der Code aus einem anderen Klassen-Template generiert, nämlich der Spezialisierung:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// erste Klasse</span>
<span class="w"> </span><span class="n">Matrix</span><span class="o">&lt;</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="o">&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// teilweise spezialisiertes Klassen-Template (zweite Klasse)</span>
<span class="w"> </span><span class="n">Matrix</span><span class="o">&lt;</span><span class="mi">15</span><span class="p">,</span><span class="mi">1</span><span class="o">&gt;</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>Wichtig zu erwähnen ist, dass beide Klassen voneinander unabhängig sind, d.&nbsp;h., sie erben weder <a href="Konstruktor" class="mw-redirect" title="Konstruktor">Konstruktoren</a> oder <a href="Destruktor" class="mw-redirect" title="Destruktor">Destruktoren</a> noch Elementfunktionen bzw. Datenelemente voneinander.
</p>
<div class="mw-heading mw-heading3"><h3 id="Spezialisierung_bei_Funktions-Templates">Spezialisierung bei Funktions-Templates</h3></div>
<p>Im Unterschied zu Klassen-Templates sind Funktions-Templates laut Standard nicht teilweise spezialisierbar (nur vollständig). Allerdings wird von der Spezialisierung von Funktions-Templates allgemein abgeraten, da die Regeln für die Bestimmung der „am besten passenden“ Funktion sonst zu unintuitiven Ergebnissen führen können.<sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p><p>Durch Überladen von Funktions-Templates mit anderen Funktions-Templates kann man in den meisten Fällen das Gleiche erreichen wie durch die (nicht zulässige) teilweise Spezialisierung. Die Erweiterung selbst läuft gewöhnlich sehr intuitiv ab:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="c1">// Generische Funktion</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">U</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>

<span class="c1">// Überladenes Funktions-Template</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>

<span class="c1">// Vollständig spezialisiert; immer noch Template</span>
<span class="k">template</span><span class="o">&lt;&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
</pre></div>
<p>Hierbei muss allerdings beachtet werden, dass ein expliziter Aufruf wie <code>f&lt;int,int&gt;()</code> <i>nicht</i> zum gewünschten Ergebnis führt. Dieser Aufruf würde die generische Funktion statt der voll spezialisierten aufrufen. Ein Aufruf von <code>f&lt;int&gt;()</code> hingegen ruft nicht die erste überladene Template-Funktion auf, sondern die voll spezialisierte. Unterlässt man explizite Aufrufe, funktioniert normalerweise alles, wie es logisch scheint (<code>f(3, 3)</code> ruft die voll spezialisierte Funktion auf, <code>f(3.5, 5)</code> die teilweise spezialisierte (erste überladene Funktion) und <code>f(3.5, 2.0)</code> die generische). Mit dieser Art der Spezialisierung sollte man also vorsichtig sein und, wenn möglich, gleich vollständig spezialisieren.
</p><p>Falls diese Technik aus jedwedem Grund im konkreten Fall nicht anwendbar ist – z.&nbsp;B. wenn ein Template von Klassenmethoden spezialisiert werden soll, ohne die Klassendefinition zu erweitern – so kann man auch das Problem der Spezialisierung auf ein Template einer Hilfsklasse verlagern:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Example</span><span class="w"> </span><span class="p">{</span>
<span class="k">private</span><span class="o">:</span>
<span class="w"> </span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">Frobnicator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">do_frobnicate</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">param</span><span class="p">);</span>
<span class="w"> </span><span class="p">};</span>

<span class="k">public</span><span class="o">:</span>
<span class="w"> </span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">frobnicate</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">param</span><span class="p">);</span>
<span class="p">};</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">Example</span><span class="o">::</span><span class="n">frobnicate</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">param</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Frobnicator soll die eigentliche Arbeit verrichten</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">Frobnicator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">do_frobnicate</span><span class="p">(</span><span class="n">param</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">Example</span><span class="o">::</span><span class="n">Frobnicator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">do_frobnicate</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">param</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Standardimplementierung ...</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;&gt;</span>
<span class="kt">int</span><span class="w"> </span><span class="n">Example</span><span class="o">::</span><span class="n">Frobnicator</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;::</span><span class="n">do_frobnicate</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">param</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// ints werden auf andere Weise "frobnifiziert"</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">param</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">param</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">7</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">param</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">foobar</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Template-Parameter">Template-Parameter</h2></div>
<p>Templates können vier Arten von Parametern haben: Typparameter, Nichttyp-Parameter, Template-Parameter und sogenannte Parameter-Packs, mit denen Templates mit einer variablen Anzahl von Parametern definiert werden können.
</p>
<div class="mw-heading mw-heading3"><h3 id="Typ-Parameter">Typ-Parameter</h3></div>
<p>Templates mit Typ-Parametern entsprechen in etwa den generischen Typen anderer Programmiersprachen. Als Typ-Parameter kann jeder beliebige Datentyp verwendet werden, wobei je nach Verwendung des Typ-Parameters innerhalb des Templates die Menge der Parametertypen, mit denen das Template instanziiert werden kann, beschränkt ist.
</p><p>Die Container der C++-Standardbibliothek verwenden unter anderem Typ-Parameter, um für alle Datentypen, auch benutzerdefinierte, geeignete Container zur Verfügung zu stellen.
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Vector</span><span class="w"> </span><span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w"> </span><span class="n">Vector</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="n">rep</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
<span class="w"> </span><span class="n">Vector</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">_size</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="n">rep</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">T</span><span class="p">[</span><span class="n">_size</span><span class="p">]),</span><span class="w"> </span><span class="n">size</span><span class="p">(</span><span class="n">_size</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
<span class="w"> </span><span class="o">~</span><span class="n">Vector</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">delete</span><span class="p">[]</span><span class="w"> </span><span class="n">rep</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">rep</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">size</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Nichttyp-Parameter">Nichttyp-Parameter</h3></div>
<p>Nichttyp-Parameter (engl. <span lang="en"><i>non-type template parameter</i></span>) sind konstante, zur Übersetzungszeit bekannte, Werte, mit denen Größen, Verfahren oder Prädikate als Template-Parameter übergeben werden können. Als Nichttyp-Template-Parameter sind erlaubt:
</p>
<ul><li>ganzzahlige Konstanten (inklusive Zeichenkonstanten),</li>
<li>Zeigerkonstanten (Daten- und Funktionszeiger, inklusive Zeiger auf Member-Variablen und -Funktionen) und</li>
<li>Zeichenkettenkonstanten.</li></ul>
<p>Verwendung finden Nichttyp-Parametern z.&nbsp;B. als Größenangabe bei <code>std::array</code> oder als Sortier- und Suchkriterium bei vielen Algorithmen der Standardbibliothek, wie z.&nbsp;B. <code>std::sort</code>, <code>std::find_if</code> oder <code>std::for_each</code>.
</p>
<div class="mw-heading mw-heading3"><h3 id="Template-Templates">Template-Templates</h3></div>
<p>Als <i>Template-Templates</i> werden Konstruktionen bezeichnet, bei denen Templates wiederum Templates als Parameter übernehmen. Sie stellen einen weiteren Abstraktionsmechanismus zur Verfügung. Im folgenden Beispiel wird sowohl der Typ als auch der verwendete Container angegeben; letzterer mit Hilfe eines Template-Template-Parameters:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="o">&gt;</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Container</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Type</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Example</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Container</span><span class="o">&lt;</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="w"> </span><span class="o">&lt;</span><span class="n">Type</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">baz</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
<p>Beispiel zur Verwendung:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="n">Example</span><span class="w"> </span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">deque</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">example</span><span class="p">;</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Parameter-Packs">Parameter-Packs</h3></div>
<p>Seit C++11 gibt es die Möglichkeit, Templates mit variabler Anzahl von Template-Parametern zu definieren. Diese werden – wie bei Funktionen und Makros mit variabler Parameteranzahl – mit <code>...</code> gekennzeichnet:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span></span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="p">...</span><span class="w"> </span><span class="n">Values</span><span class="o">&gt;</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">tuple</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Definition ausgelassen</span>
<span class="p">};</span>

<span class="c1">// Verwendung:</span>
<span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="o">&gt;</span><span class="w"> </span><span class="n">t</span><span class="p">;</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Siehe_auch">Siehe auch</h2></div>
<ul><li><a href="C%2B%2B-Metaprogrammierung" title="C++-Metaprogrammierung">C++-Metaprogrammierung</a></li>
<li><a href="Duck-Typing" title="Duck-Typing">Duck-Typing</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Literatur">Literatur</h2></div>
<ul><li>David Vandervoorde, Nicolai M. Josuttis: <cite style="font-style:italic">C++ Templates</cite>. The Complete Guide. Addison-Wesley Professional, 2003, ISBN 0-201-73484-2.<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rfr_id=info:sid/de.wikipedia.org:Template+%28C%2B%2B%29&amp;rft.au=David+Vandervoorde%2C+Nicolai+M.+Josuttis&amp;rft.btitle=C%2B%2B+Templates&amp;rft.date=2003&amp;rft.genre=book&amp;rft.isbn=0201734842&amp;rft.pub=Addison-Wesley+Professional" style="display:none">&nbsp;</span></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Einzelnachweise">Einzelnachweise</h2></div>
<ol class="references">
<li id="cite_note-Stroustrup-1"><span class="mw-cite-backlink"><a href="#cite_ref-Stroustrup_1-0">↑</a></span> <span class="reference-text"><a href="Bjarne_Stroustrup" title="Bjarne Stroustrup">Bjarne Stroustrup</a>: <cite style="font-style:italic">Die C++-Programmiersprache</cite>. 4. Auflage. Addison-Wesley, 2009, ISBN 978-3-8273-2823-6.<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rfr_id=info:sid/de.wikipedia.org:Template+%28C%2B%2B%29&amp;rft.au=Bjarne+Stroustrup&amp;rft.btitle=Die+C%2B%2B-Programmiersprache&amp;rft.date=2009&amp;rft.edition=4.&amp;rft.genre=book&amp;rft.isbn=9783827328236&amp;rft.pub=Addison-Wesley" style="display:none">&nbsp;</span></span>
</li>
<li id="cite_note-2"><span class="mw-cite-backlink"><a href="#cite_ref-2">↑</a></span> <span class="reference-text"><span class="cite"><a rel="nofollow" class="external text" href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf"><i>Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle.</i></a> (PDF)<span class="Abrufdatum"> Abgerufen am 26.&nbsp;Mai 2017</span>.</span><span style="display: none;" class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Fde.wikipedia.org%3ATemplate+%28C%2B%2B%29&amp;rft.title=Oracle+Technology+Network+for+Java+Developers+%7C+Oracle+Technology+Network+%7C+Oracle&amp;rft.description=Oracle+Technology+Network+for+Java+Developers+%7C+Oracle+Technology+Network+%7C+Oracle&amp;rft.identifier=http%3A%2F%2Fjava.sun.com%2Fj2se%2F1.5%2Fpdf%2Fgenerics-tutorial.pdf">&nbsp;</span></span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><a href="#cite_ref-3">↑</a></span> <span class="reference-text"><span class="cite"><a rel="nofollow" class="external text" href="http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx"><i>An Introduction to C# Generics.</i></a><span class="Abrufdatum"> Abgerufen am 26.&nbsp;Mai 2017</span> (englisch).</span><span style="display: none;" class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Fde.wikipedia.org%3ATemplate+%28C%2B%2B%29&amp;rft.title=An+Introduction+to+C%23+Generics&amp;rft.description=An+Introduction+to+C%23+Generics&amp;rft.identifier=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fms379564%28VS.80%29.aspx&amp;rft.language=en">&nbsp;</span></span>
</li>
<li id="cite_note-4"><span class="mw-cite-backlink"><a href="#cite_ref-4">↑</a></span> <span class="reference-text">Herb Sutter: <cite style="font-style:italic">Why Not Specialize Function Templates?</cite> In: <cite style="font-style:italic">C/C++ Users Journal</cite>. <span style="white-space:nowrap">Band<span style="display:inline-block;width:.2em">&nbsp;</span>7</span>, <span style="white-space:nowrap">Nr.<span style="display:inline-block;width:.2em">&nbsp;</span>19</span>, Juli 2001 (<a rel="nofollow" class="external text" href="http://www.gotw.ca/publications/mill17.htm">gotw.ca</a>).<span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Ajournal&amp;rfr_id=info:sid/de.wikipedia.org:Template+%28C%2B%2B%29&amp;rft.atitle=Why+Not+Specialize+Function+Templates%3F&amp;rft.au=Herb+Sutter&amp;rft.date=2001-07&amp;rft.genre=journal&amp;rft.issue=19&amp;rft.jtitle=C%2FC%2B%2B+Users+Journal&amp;rft.volume=7" style="display:none">&nbsp;</span></span>
</li>
</ol></div><!--htdig_noindex--><div><div class="zim-footer">
Dieser Artikel wurde von <a class="external text" title="Zuletzt bearbeitet am 2025-10-16" href="https://de.wikipedia.org/wiki/?title=Template_(C%2B%2B)&amp;oldid=260639873">Wikipedia</a> herausgegeben. Der Text ist unter <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.de">Creative Commons Attribution-Share Alike 4.0</a> verfügbar, sofern nicht anders angegeben. Für die Mediendateien können zusätzliche Bedingungen gelten.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
<script src="./_webp_/webpHandler.js"></script>

</body></html>